home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / gopher1.12 / gopherd / waisgopher.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-21  |  20.7 KB  |  857 lines

  1. /********************************************************************
  2.  * $Author: lindner $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1992/12/10 23:13:27 $
  5.  * $Source: /home/mudhoney/GopherSrc/release1.11/gopherd/RCS/waisgopher.c,v $
  6.  * $Status: $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: waisgopher.c
  14.  * Routines to translate from gopher protocol to wais protocol
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: waisgopher.c,v $
  18.  * Revision 1.1  1992/12/10  23:13:27  lindner
  19.  * gopher 1.1 release
  20.  *
  21.  *
  22.  *********************************************************************/
  23.  
  24.  
  25. /* Wais to gopher gateway code.
  26.  
  27.    Paul Lindner, March 1992
  28.    <lindner@boombox.micro.umn.edu>
  29. */
  30.  
  31. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  32.    No guarantees or restrictions.  See the readme file for the full standard
  33.    disclaimer.
  34.    
  35.    Brewster@think.com
  36. */
  37.  
  38. #if defined(WAISSEARCH)   /*** Only compile this if we have WAIS ***/
  39.  
  40. #include "gopherd.h"
  41.  
  42. #if defined(_AIX)
  43. #define ANSI_LIKE
  44. #endif
  45.  
  46. #include <ctype.h>
  47. #include <ui.h>
  48. #include <docid.h>
  49.  
  50. #define MAIN
  51. #define sockets_h
  52. #include "wais.h"
  53.  
  54. #define WAISSEARCH_DATE "Fri Sep 13 1991"
  55.  
  56.  
  57. /**** Needed by wais-8-b5... Ick... ***/
  58.  
  59. char *sdir=NULL;
  60. char *cdir=NULL;
  61.  
  62. /**** Used by something in the source reading routines. ***/
  63. void
  64. PrintStatus(str)
  65. char * str;
  66. {
  67.      return;
  68. }
  69.  
  70. void find_value(source, key, value, value_size)
  71. char *source, *key, *value;
  72. int value_size;
  73. {
  74.   char ch;
  75.   long position = 0;  /* position in value */
  76.   char *pos =strstr(source, key); /* address into source */
  77.  
  78.   value[0] = '\0';        /* initialize to nothing */
  79.  
  80.   if(NULL == pos)
  81.     return;
  82.  
  83.   pos = pos + strlen(key);
  84.   ch = *pos;
  85.   /* skip leading quotes and spaces */
  86.   while((ch == '\"') || (ch == ' ')) {
  87.     pos++; ch = *pos;
  88.   }
  89.   for(position = 0; pos < source + strlen(source); pos++){
  90.     if((ch = *pos) == ' ') {
  91.       value[position] = '\0';
  92.       return;
  93.     }
  94.     value[position] = ch;
  95.     position++;
  96.     if(position >= value_size){
  97.       value[value_size - 1] = '\0';
  98.       return;
  99.     }
  100.   }
  101.   value[position] = '\0';
  102. }
  103.  
  104. /****/
  105.  
  106. void ZapTabs(in)
  107.   char *in;
  108. {
  109.      /** replace tabs with a space... **/
  110.      while (*in != '\0') {
  111.       if (*in == '\t')
  112.            *in = ' ';
  113.       in ++;
  114.      }
  115. }
  116.  
  117. void
  118. Send_binary_record(record, sockfd)
  119.   WAISDocumentText *record;
  120.   int sockfd;
  121. {
  122.      long count;
  123.      long ch;
  124.      char output[512];
  125.      int outputptr = 0;
  126.  
  127.      writen(sockfd, record->DocumentText->bytes, record->DocumentText->size);
  128. }
  129.  
  130.  
  131. /*** Modified from ../ir/ui.c to add \r\n at the ends of the line... ***/
  132. void
  133. Mydisplay_text_record_completely(record,quote_string_quotes, sockfd)
  134.   WAISDocumentText *record;
  135.   boolean quote_string_quotes;
  136.   int sockfd;
  137. {
  138.      long count;
  139.      unsigned char ch;
  140.      unsigned char output[512];
  141.      int outputptr = 0;
  142.  
  143.      for(count = 0; count < record->DocumentText->size; count++){
  144.       
  145.       ch = (unsigned char)record->DocumentText->bytes[count];
  146.       
  147.       switch (ch) {
  148.  
  149.       case 27:
  150.            /* then we have an escape code */
  151.            /* if the next letter is '(' or ')', then ignore two letters */
  152.            if('(' == record->DocumentText->bytes[count + 1] ||
  153.           ')' == record->DocumentText->bytes[count + 1])
  154.             count += 1;             /* it is a term marker */
  155.            else count += 4;        /* it is a paragraph marker */
  156.            break;
  157.       case '\t':
  158.            output[outputptr++] = ch;
  159.            break;
  160.       case '\r':
  161.            if ('\n' == record->DocumentText->bytes[count + 1])
  162.             break;
  163.       case '\n':
  164.            if (DEBUG) printf("Got a return\n");
  165.            output[outputptr++] = '\r';
  166.            output[outputptr++] = '\n';
  167.            break;
  168.       default:
  169.            if (isprint(ch)){
  170.             if(quote_string_quotes && ch == '"') {
  171.              output[outputptr++] = '/';
  172.              output[outputptr++] = '/';
  173.             }
  174.             output[outputptr++] = ch;
  175.            } 
  176.       }
  177.  
  178.       if (outputptr >500) {
  179.            output[outputptr++] = '\0';
  180.            writestring(sockfd, output);
  181.            outputptr = 0;
  182.       }
  183.      }
  184.  
  185.  
  186.      /*** Write out the rest of the buffer...  ***/
  187.  
  188.      output[outputptr++] = '\0';
  189.      writestring(sockfd, output);
  190. }
  191.  
  192.  
  193.  
  194. /* modified from Jonny G's version in ui/question.c */
  195. void showDiags(d)
  196.   diagnosticRecord **d;
  197. {
  198.      long i;
  199.      
  200.      for (i = 0; d[i] != NULL; i++) {
  201.       if (d[i]->ADDINFO != NULL) {
  202.            printf("Code: %s, %s\n", d[i]->DIAG, d[i] ->ADDINFO);
  203.       }
  204.      }
  205. }
  206.  
  207.  
  208.  
  209. int
  210. acceptable(foo)
  211.   char foo;
  212. {
  213.      if (foo == '\t' || foo == '\r' || foo == '\n' || foo == '\0')
  214.       return(0);
  215.      else if (!isprint(foo))
  216.       return(0);
  217.      else
  218.       return(1);
  219. }
  220.  
  221.  
  222. static char * hex = "0123456789ABCDEF";
  223.  
  224. /*
  225.  * DocId_to_Gopher transforms a docid into a character string suitable for
  226.  * transmission
  227.  */
  228.  
  229. char *DocId_to_Gopher(docid, docsize)
  230.   any *docid;
  231.   int docsize;
  232. {
  233.      static char GopherString[512];
  234.      char *q = GopherString;
  235.      char *p;
  236.      int l, i;
  237.           
  238.      /** First lets stick on the size of the document first **/
  239.  
  240.      sprintf(GopherString, "%d", docsize);
  241.      q += strlen(GopherString);
  242.      *q++ = ':';
  243.  
  244.      for (p=docid->bytes; (p < docid->bytes + docid->size) && q<&GopherString[512];) {
  245.       if (*p >= 10) {
  246.            ; /* Bad thing happened, can't understand docid, punt */
  247.            return(NULL);
  248.       }
  249.       
  250.       *q++ = (*p++) + '0';   /* Record Type */
  251.       *q++ = '=';            /* Seperate */
  252.       l = *p++;              /* Length */
  253.       for (i=0; i<l; i++, p++) {
  254.            if (acceptable(*p)==0) {
  255.             *q++ = '%';
  256.             *q++ = hex[(*p) >> 4];
  257.             *q++ = hex[(*p) & 15];
  258.            }
  259.            else *q++ = *p;
  260.       }
  261.       *q++ = ';';
  262.      }
  263.      *q++ = 0;
  264.      return(GopherString);
  265. }
  266.  
  267. /*
  268.  * Gstring is a name produced by DocID_to_Gopher
  269.  */
  270.  
  271. any *Gopher_to_DocId(Gstring, DocSize)
  272.   char *Gstring;
  273.   int *DocSize;
  274. {
  275.      static any docid;
  276.      char *outptr;
  277.      char *inptr; 
  278.      char *sor;
  279.      char *eqptr;  
  280.      char *semiptr;
  281.      int size; 
  282.  
  283.      /* Strip off the Document size first.... */
  284.      
  285.      inptr = strchr(Gstring, ':');
  286.      if (inptr == NULL) 
  287.       return;
  288.  
  289.      *DocSize = atoi(Gstring);
  290.      
  291.      Gstring = inptr +1;
  292.  
  293.      for (size=0, inptr=Gstring; *inptr; inptr++) {
  294.       size ++;
  295.       if (*inptr == ';') 
  296.            size--;
  297.       else if (*inptr ==  '%') 
  298.            size -=2;
  299.       
  300.      }
  301.  
  302.      docid.size = size;
  303.  
  304.      docid.bytes = (char *) malloc(docid.size);
  305.      outptr = docid.bytes;
  306.  
  307.      for (inptr = Gstring; *inptr;) {
  308.       *outptr++ = *inptr++ - '0';  /* Record Type */
  309.       eqptr = strchr(inptr, '=');
  310.       if (!eqptr)
  311.            return(0);
  312.       semiptr = strchr(inptr, ';');
  313.       if (!semiptr)
  314.            return(0);
  315.       sor = outptr;
  316.       outptr++;
  317.  
  318.       for (inptr = eqptr+1; *inptr!=';' ; ) {
  319.            if (*inptr == '%') {
  320.             char c;
  321.             unsigned int b;
  322.             
  323.             inptr++;
  324.             c = *inptr++;
  325.             b = from_hex(c);
  326.             c = *inptr++;
  327.             if (!c) break;
  328.             *outptr++ = (b<<4) + from_hex(c);
  329.            } else {
  330.             *outptr++ = *inptr++;
  331.            }
  332.       }
  333.       
  334.       *sor = (outptr-sor-1);
  335.       inptr++;
  336.      }
  337.      
  338.      return(&docid);
  339.  
  340. }
  341.             
  342.  
  343.  
  344. /*-----------------------------------------------------------------*/
  345.  
  346. /* modified from tracy shen's version in wutil.c
  347.  * displays either a text record of a set of headlines.
  348.  */
  349. void
  350. display_search_response(response, hostname, port, dbname, SourceName, sockfd)
  351.   SearchResponseAPDU *response;
  352.   char *hostname, *port, *dbname, *SourceName;
  353.   int sockfd;
  354. {
  355.      WAISSearchResponse  *info;
  356.      long i, k;
  357.      struct sockaddr_in serv_addr;
  358.      int length = sizeof(serv_addr);
  359.      GopherObj *gs = NULL;
  360.      GopherDirObj *gd = NULL;
  361.      char gopherpath[1024];
  362.  
  363.      gs = GSnew();
  364.      gd = GDnew(64);
  365.  
  366.      if ( response->DatabaseDiagnosticRecords != 0 ) {
  367.       info = (WAISSearchResponse *)response->DatabaseDiagnosticRecords;
  368.       i =0; 
  369.           
  370.       if (info->Diagnostics != NULL)
  371.            showDiags(info->Diagnostics);
  372.       
  373.       if ( info->DocHeaders != 0 ) {
  374.            k =0;
  375.            while (info->DocHeaders[k] != 0 ) {
  376.             i++;
  377.             ZapCRLF(info->DocHeaders[k]->Headline);
  378.             ZapTabs(info->DocHeaders[k]->Headline);
  379.             
  380.             GSinit(gs);
  381.  
  382.             GSsetTitle(gs, info->DocHeaders[k]->Headline);
  383.             
  384.             sprintf(gopherpath, "waisdocid:%s:%s:%s",
  385.                 SourceName,
  386.                 info->DocHeaders[k]->Types[0], 
  387.                 DocId_to_Gopher(info->DocHeaders[k]->DocumentID,
  388.                         info->DocHeaders[k]->DocumentLength));
  389.             GSsetPath(gs, gopherpath);
  390.             GSsetHost(gs, Zehostname);
  391.             GSsetPort(gs, GopherPort);
  392.  
  393.             if (strcmp(info->DocHeaders[k]->Types[0], "TEXT") == 0) {
  394.              GSsetType(gs, A_FILE);
  395.             }
  396.             else if (strcmp(info->DocHeaders[k]->Types[0],"GIF")==0) {
  397.              GSsetType(gs, A_GIF);
  398.             }
  399.             else if (strcmp(info->DocHeaders[k]->Types[0],"PICT")==0) {
  400.              GSsetType(gs, A_IMAGE);
  401.             }
  402.             else if (strcmp(info->DocHeaders[k]->Types[0],"WSRC")==0) {
  403.              GSsetType(gs, A_INDEX);
  404.             }
  405.             else
  406.              GSsetType(gs, A_UNIXBIN);
  407.             
  408.             GDaddGS(gd, gs);
  409.             k++;
  410.            }
  411.            
  412.            GDtoNet(gd, sockfd);
  413.            writestring(sockfd, ".\r\n");
  414.       }
  415.  
  416.       if ( info->Text != 0 ) {
  417.            k =0;
  418.            while ((info->Text[k] != 0) ) {
  419.             i++;
  420.             printf("\n    Text record %2d, ", i);
  421.             Mydisplay_text_record_completely( info->Text[k++], false, sockfd);
  422.            }
  423.       }
  424.      }
  425. }
  426.  
  427.  
  428. /*** Find server, database, and service
  429.  *** This routine recognizes the hack where the filename is
  430.  *** (server database service)
  431.  ***/
  432. MyReadSource(Moo, filename, sockfd)
  433.   Source Moo;
  434.   char   *filename;
  435.   int sockfd;
  436. {
  437.      FILE *dotsrc;
  438.      char  *cp;
  439.      if (filename == NULL)
  440.       Abortoutput(sockfd, "No Filename!");
  441.  
  442.      if (*filename == '(' && filename[strlen(filename)-1] == ')') {
  443.       cp = strchr(filename, ' ');
  444.       if (cp==NULL)
  445.            Abortoutput(sockfd, "malformed filename");
  446.       *cp = '\0';
  447.       strcpy(Moo->server, filename+1);
  448.       *cp = ' ';
  449.   
  450.       filename = cp+1;
  451.       cp = strchr(filename, ' ');
  452.       if (cp==NULL)
  453.            Abortoutput(sockfd, "malformed filename");
  454.       *cp = '\0';
  455.       strcpy(Moo->database, filename);
  456.       *cp = ' ';
  457.  
  458.       filename = cp +1;
  459.       filename[strlen(filename)] = '\0';
  460.       strcpy(Moo->service, filename);
  461.      }
  462.      else {
  463.       dotsrc = rfopen(filename, "r");
  464.       if (dotsrc == NULL) {
  465.            char tmpstr[256];
  466.            sprintf(tmpstr, "File '%s' does not exist", filename);
  467.            Abortoutput(sockfd, tmpstr), exit(-1);
  468.       }
  469.  
  470.       ReadSource(Moo, dotsrc);
  471.       fclose(dotsrc);
  472.      }
  473. }
  474.       
  475.       
  476.          
  477.  
  478.  
  479.  
  480. #define MAX_KEYWORDS_LENGTH 1000
  481. #define MAX_SERVER_LENGTH 1000
  482. #define MAX_DATABASE_LENGTH 1000
  483. #define MAX_SERVICE_LENGTH 1000
  484. #define MAXDOCS 40
  485.  
  486. /******************************************************************/
  487.  
  488. void SearchRemoteWAIS(sockfd, inputline)
  489.   int sockfd;
  490.   char *inputline;
  491. {
  492.      char* request_message = NULL; /* arbitrary message limit */
  493.      char* response_message = NULL; /* arbitrary message limit */
  494.      long request_buffer_length;    /* how of the request is left */
  495.      SearchResponseAPDU  *query_response;
  496.      SearchResponseAPDU  *retrieval_response;
  497.      WAISSearchResponse  *query_info, *retrieval_info;
  498.      char server_name[MAX_SERVER_LENGTH + 1];    
  499.      char service[MAX_SERVICE_LENGTH + 1];
  500.      char database[MAX_DATABASE_LENGTH + 1];
  501.      long count;
  502.      FILE *connection;
  503.      char *keywords;
  504.      FILE *Dotsrcfile;
  505.      char *SourceName;
  506.      char *WaisGatePort=NULL;
  507.      Source Moo;
  508.      char *cp;
  509.  
  510.  
  511.      server_name[0] = '\0';  /* null it out */
  512.      database[0] = '\0';     /* null it out */
  513.      service[0] = '\0';      /* null it out */
  514.  
  515.  
  516.      /**
  517.       ** Next load up the name of the source...
  518.       */
  519.      
  520.      cp = strchr(inputline, '\t');
  521.      keywords = cp + 1;
  522.      
  523.      if (cp == NULL) {
  524.       /** An error occured, probably old client software... **/
  525.       writestring(sockfd, ".\r\n");
  526.      } else
  527.       *cp = '\0';
  528.      
  529.      SourceName= inputline;
  530.      
  531.      Moo = (Source)malloc(sizeof(_Source));
  532.      bzero(Moo, sizeof(_Source));
  533.  
  534.      MyReadSource(Moo, SourceName, sockfd);
  535.      strcpy(server_name, Moo->server);
  536.      strcpy(database, Moo->database);
  537.      strcpy(service, Moo->service);
  538.      
  539.      if (server_name[0] == 0)
  540.       connection = NULL;
  541.      
  542.      else if ((connection=connect_to_server(server_name,atoi(service))) == NULL) 
  543.      {
  544.       char Errorstr[256];
  545.  
  546.       sprintf(Errorstr,"Error openning connection to %s via service %s.", 
  547.           server_name, service);
  548.       Abortoutput(sockfd, Errorstr);
  549.       exit(-1);
  550.      }
  551.      
  552.      request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
  553.      response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
  554.      {
  555.       char userInfo[256];
  556.  
  557.       sprintf(userInfo, "waisgopher %s, from host: %s", VERSION, Zehostname);
  558.       init_connection(request_message, response_message,
  559.               MAX_MESSAGE_LEN,
  560.               connection,
  561.               userInfo);
  562.      }
  563.      request_buffer_length = MAX_MESSAGE_LEN; /* how of the request is left */
  564.      
  565.      if(NULL ==
  566.     generate_search_apdu(request_message + HEADER_LENGTH, 
  567.                  &request_buffer_length, 
  568.                  keywords, database, NULL, MAXDOCS))
  569.       Abortoutput(sockfd, "request too large");
  570.      
  571.      
  572.      if(0 ==
  573.     interpret_message(request_message, 
  574.               MAX_MESSAGE_LEN - request_buffer_length, 
  575.               response_message,
  576.               MAX_MESSAGE_LEN,
  577.               connection,
  578.               false    /* true verbose */
  579.               )) { /* perhaps the server shut down on us, let's see: */
  580.       if ( connection != NULL) {
  581.            fclose(connection);
  582.            if ((connection=connect_to_server(server_name,atoi(service))) == NULL) 
  583.            {
  584.             char Errorstr[256];
  585.  
  586.             sprintf(Errorstr, "Error openning connection to %s via service %s.\n",
  587.                server_name, service);
  588.             Abortoutput(sockfd, Errorstr);
  589.            }
  590.  
  591.            if(0 ==
  592.           interpret_message(request_message, 
  593.                     MAX_MESSAGE_LEN - request_buffer_length, 
  594.                     response_message,
  595.                     MAX_MESSAGE_LEN,
  596.                     connection,
  597.                     false /* true verbose */
  598.                     ))
  599.             Abortoutput(sockfd, "really couldn't deliver message");
  600.       }
  601.       else
  602.            Abortoutput(sockfd, "returned message too large");
  603.      }
  604.      
  605.      readSearchResponseAPDU(&query_response, response_message + HEADER_LENGTH);
  606.      
  607.      display_search_response(query_response, server_name, service, database, SourceName, sockfd);
  608.      
  609.      freeWAISSearchResponse(query_response->DatabaseDiagnosticRecords);         
  610.      freeSearchResponseAPDU( query_response);
  611.      
  612.      /*** close it down ***/
  613.      
  614.      close_connection(connection);
  615.      
  616.      s_free(request_message);
  617.      s_free(response_message);
  618.      
  619. }
  620.  
  621.  
  622.  
  623.  
  624. /*******************************************************/
  625.  
  626. void
  627. Fetchdocid(sockfd, inputline)
  628.   int sockfd;
  629.   char *inputline;
  630. {
  631.      any *docid;
  632.      int DocLen;
  633.      int count;
  634.      char* request_message = NULL; /* arbitrary message limit */
  635.      char* response_message = NULL; /* arbitrary message limit */
  636.      long request_buffer_length;    /* how of the request is left */
  637.      char server_name[MAX_SERVER_LENGTH + 1];    
  638.      char service[MAX_SERVICE_LENGTH + 1];
  639.      char database[MAX_DATABASE_LENGTH + 1];
  640.      SearchResponseAPDU  *retrieval_response;
  641.      FILE *connection;
  642.      char *SourceName;
  643.      char *WaisGatePort=NULL;
  644.      Source Moo;
  645.      char *DocIdString;
  646.      FILE *Dotsrcfile;
  647.      char *type;
  648.      char *searchwords;
  649.           
  650.      server_name[0] = '\0';  /* null it out */
  651.      database[0] = '\0';     /* null it out */
  652.      service[0] = '\0';      /* null it out */
  653.  
  654.  
  655.      DocIdString = strchr(inputline, ':');
  656.      if (DocIdString == NULL) {
  657.       Abortoutput(sockfd, "Malformed docid");
  658.       return;
  659.      }
  660.      else {
  661.       *DocIdString = '\0';
  662.       DocIdString++;
  663.       type = DocIdString;
  664.       DocIdString = strchr(type, ':') + 1;
  665.       searchwords = strrchr(DocIdString, '\t');
  666.       if (searchwords != NULL) {
  667.            *(searchwords) = '\0';
  668.            searchwords++;
  669.       }
  670.      }
  671.  
  672.      SourceName = inputline;
  673.      
  674.      Moo = (Source)malloc(sizeof(_Source));
  675.      bzero(Moo, sizeof(_Source));
  676.  
  677.      MyReadSource(Moo, SourceName);
  678.  
  679.      strcpy(server_name, Moo->server);
  680.      strcpy(database, Moo->database);
  681.      strcpy(service, Moo->service);
  682.      
  683.      if (server_name[0] == 0)
  684.       connection = NULL;
  685.  
  686.  
  687.      else if ((connection=connect_to_server(server_name,atoi(service))) == NULL) 
  688.      {
  689.       char Errorstr[256];
  690.  
  691.       sprintf(Errorstr,"Error openning connection to %s via service %s.", 
  692.           server_name, service);
  693.       Abortoutput(sockfd, Errorstr);
  694.       return;
  695.      }
  696.      request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
  697.      response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
  698.  
  699.      docid = Gopher_to_DocId(DocIdString, &DocLen);
  700.      
  701.      /*** First let's transform the first word into a docid ***/
  702.      /*** What we need from net:  DocumentLength, Types: (TEXT!), docid, **/
  703.      
  704.      for(count = 0; 
  705.      count * CHARS_PER_PAGE <
  706.      DocLen;
  707.      count++){
  708.       
  709.       request_buffer_length = MAX_MESSAGE_LEN; /* how of the request is left */
  710.       if(0 ==
  711.          generate_retrieval_apdu(request_message + HEADER_LENGTH,
  712.                      &request_buffer_length, 
  713.                      docid, 
  714.                      CT_byte,
  715.                      count * CHARS_PER_PAGE,
  716.                      MIN((count + 1) * CHARS_PER_PAGE,
  717.                      DocLen),
  718.                      type,
  719.                      database
  720.                      ))
  721.            panic("request too long");
  722.       
  723.       if(0 ==
  724.          interpret_message(request_message, 
  725.                    MAX_MESSAGE_LEN - request_buffer_length, 
  726.                    response_message,
  727.                    MAX_MESSAGE_LEN,
  728.                    connection,
  729.                    false /* true verbose */    
  730.                    )) { /* perhaps the server shut down on us, let's see: */
  731.            if ( connection != NULL) {
  732.             fclose(connection);
  733.             if ((connection=connect_to_server(server_name,atoi(service))) == NULL) 
  734.             {
  735.              fprintf (stderr, "Error openning connection to %s via service %s.\n",
  736.                   server_name, service);
  737.              exit(-1);
  738.             }
  739.             if(0 ==
  740.                interpret_message(request_message, 
  741.                      MAX_MESSAGE_LEN - request_buffer_length, 
  742.                      response_message,
  743.                      MAX_MESSAGE_LEN,
  744.                      connection,
  745.                      false /* true verbose */
  746.                      ))
  747.              panic("really couldn't deliver message");
  748.            }
  749.            else
  750.             panic("returned message too large");
  751.       }
  752.       
  753.       readSearchResponseAPDU(&retrieval_response, 
  754.                  response_message + HEADER_LENGTH);
  755.       
  756.       /* display_search_response(retrieval_response); the general thing */
  757.       if(NULL == ((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text){
  758.            display_search_response(retrieval_response);
  759.            panic("No text was returned");
  760.       }
  761.  
  762.       if (strncmp(type, "TEXT", 4) == 0) {
  763.            int k;
  764.            k = 0;
  765.            if (DEBUG) printf("Displaying text\n");
  766.            while (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[k] != 0) {
  767.             Mydisplay_text_record_completely
  768.              (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[k++], false, sockfd);
  769.            }
  770.            writestring(sockfd, ".\r\n");
  771.  
  772.       }
  773.       else if (strncmp(type, "WSRC", 4) == 0)  {
  774.           char searchline[512];
  775.           char tempfile[64];
  776.           int  tempdotsrc;
  777.           Source Moo;
  778.           FILE *Dotsrcfile;
  779.           int k;
  780.  
  781.           /*** It's a search! **/
  782.           if (DEBUG) printf("Searching!\n");
  783.           
  784.           /*** Dump out the contents of the text record on the server ***/
  785.           /*** then call SearchRemoteWAIS(), then delete file ***/
  786.           rchdir("/");
  787.           mkdir("tmp",0755);
  788.           sprintf(tempfile, "/tmp/waissearch.%d", getpid());
  789.           tempdotsrc = ropen(tempfile, O_RDWR|O_CREAT,0755);
  790.           if (tempdotsrc < 0) {
  791.            writestring(sockfd, "3couldn't make temp file\r\n.\r\n");
  792.            return;
  793.           }
  794.           Mydisplay_text_record_completely
  795.            (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[0], false, tempdotsrc);
  796.           close(tempdotsrc);
  797.  
  798.           Moo = (Source) malloc(sizeof(_Source));
  799.           bzero(Moo, sizeof(_Source));
  800.  
  801.           MyReadSource(Moo, tempfile);
  802.  
  803.           sprintf(searchline, "(%s %s %s)\t%s", Moo->server, Moo->database, Moo->service, searchwords);
  804.  
  805.           if (DEBUG) printf("%s\n", searchline);
  806.           rchdir("/");
  807.           SearchRemoteWAIS(sockfd, searchline);
  808.           
  809. /*          unlink(tempfile);*/
  810.      }
  811.       else {
  812.            int recs =0;
  813.  
  814.            if (DEBUG) printf("Displaying Binary\n");
  815.            while (1) {
  816.             if (((WAISSearchResponse*)retrieval_response->DatabaseDiagnosticRecords)->Text[recs] == NULL)
  817.              break;
  818.             Send_binary_record(((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[recs++], sockfd);
  819.            }
  820.       }
  821.      }
  822.  
  823.      freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords); 
  824.      freeSearchResponseAPDU( retrieval_response);
  825.  
  826.      /*** close it down ***/
  827.  
  828.      close_connection(connection);
  829.      
  830.      s_free(request_message);
  831.      s_free(response_message);
  832.  
  833. }
  834.  
  835. #else /* defined(WAISSEARCH) */
  836.  
  837. void
  838. SearchRemoteWAIS(sockfd, selstr)
  839.   int sockfd;
  840.   char *selstr;
  841. {
  842.      Abortoutput(sockfd, "No wais stuff in the server!!");
  843.  
  844.  
  845. }
  846.  
  847.  
  848. void
  849. Fetchdocid(sockfd, selstr)
  850.   int sockfd;
  851.   char *selstr;
  852. {
  853.      Abortoutput(sockfd, "No wais stuff in the server!!");
  854. }
  855.  
  856. #endif
  857.